package com.ccl.iot.managers;

import android.content.Context;
import android.os.Handler;
import android.os.Message;

import com.ccl.iot.App;
import com.ccl.iot.EIOT_RESULT;
import com.ccl.iot.IOTCallback;
import com.ccl.iot.IOTNetAPI;
import com.ccl.iot.IOTNetAPIEnum.ESECURITY_INFO_TYPE;
import com.ccl.iot.R;
import com.ccl.iot.huiju.LoginDialog;
import com.ccl.iot.dialogs.SecurityCodeDialog;
import com.ccl.iot.publics.ActivityProgressDialog;
import com.ccl.iot.publics.FileSystem;
import com.ccl.iot.publics.ListenerHolder;
import com.ccl.iot.publics.Messager;
import com.ccl.iot.template.ActivityDialog;

public class UserManager extends Manager {
    private static final int KEVENT_LOGIN = 1;
    private static final int KEVENT_PREPARE_LOGOUT = 2;
    private static final int KEVENT_LOGOUT = 3;

    private static final int KMESSAGE_SHOW_LOGIN_DIALOG = 1;
    private static final int KMESSAGE_SHOW_PROGRESS = 2;
    private static final int KMESSAGE_HIDE_PROGRESS = 3;

    public interface UserEventListener {
        public void onLoginEvent(boolean aCanceled);

        public void onPrepareLogout();

        public void onLogout(boolean aOK);
    }

    /*
     * Static functions
     */
    private static UserManager gDefault = null;

    public static UserManager GetDefaultManager(Context aContext, String aDBPath) {
        if (gDefault == null) {
            gDefault = new UserManager(aContext, aDBPath);
        }

        return gDefault;
    }

    public static UserManager GetDefaultManager() {
        return gDefault;
    }

    /*
     * Non-static functions
     */
    private Object iSyncLock = new Object();

    private String iNeverLoginFile = null;
    private IOTNetAPI iNetAPI = null;

    private ActivityProgressDialog iProgressDialog = null;
    private LoginDialog iLoginDialog = null;

    private volatile boolean iLogining = false;
    private volatile boolean iLoginError = false;
    private volatile boolean iLoginCanceled = false;

    private UserManager(Context aContext, String aDBPath) {
        super(aContext);

        iNeverLoginFile = aDBPath + "NeverLogin.opt";
        onCreate();
    }

    private void onCreate() {
        super.create();

        iNetAPI = IOTNetAPI.GetInstance();

        iNetAPI.setLoginResultCallback(iLoginResultListener);
    }

    @Override
    public void onResume() {
        super.onResume();

        login(false);
    }

    @Override
    public void onSuspend() {
        super.onSuspend();

        iLogining = false;
        iLoginError = false;
        iLoginCanceled = false;

        //TODO 当程序回到后台运行时不再调用
        //        onLogon(false);
    }

    @Override
    public boolean filteError(int aError) {
        if (aError == EIOT_RESULT.EIOT_RESULT_FATAL_USER_NOT_EXIST) {
            return true;
        }

        return false;
    }

    public boolean isLoginCanceled() {
        return iLoginCanceled;
    }

    private Handler iHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg != null) {
                if (msg.what == KMESSAGE_SHOW_LOGIN_DIALOG) {
                    boolean tForce = false;

                    if (msg.obj != null && msg.obj instanceof Boolean) {
                        tForce = (Boolean) msg.obj;
                    }
                    if (isLogon() == false && iLoginDialog == null) {
                        LoginDialog.Show(App.GetInstance(), iLoginListener, tForce);
                    }
                } else if (msg.what == KMESSAGE_SHOW_PROGRESS && msg.obj != null) {
                    if (isLogon() == false && iProgressDialog == null) {
                        ActivityProgressDialog.Show(App.GetInstance(), ActivityProgressDialog.KSTYLE_VERTICAL, msg.obj, iProgressListener);
                    }
                } else if (msg.what == KMESSAGE_HIDE_PROGRESS) {
                    if (iProgressDialog != null && iProgressDialog.isShowing()) {
                        iProgressDialog.dismiss();
                    }

                    Messager.Show(msg.obj);
                }
            }
        }
    };

    private void showProgress(Object aMessage) {
        if (iHandler != null) {
            iHandler.sendMessage(Message.obtain(iHandler, KMESSAGE_SHOW_PROGRESS, aMessage));
        }
    }

    private void hideProgress(Object aReason) {
        if (iHandler != null) {
            if (iHandler.hasMessages(KMESSAGE_SHOW_PROGRESS)) {
                iHandler.removeMessages(KMESSAGE_SHOW_PROGRESS);
            }

            iHandler.sendMessage(Message.obtain(iHandler, KMESSAGE_HIDE_PROGRESS, aReason));
        }
    }

    public boolean isNeedLogin() {
        return FileSystem.FileExists(iNeverLoginFile, false) == false;
    }

    public void setNeedLogin(boolean aNeed) {
        if (aNeed) {
            FileSystem.DeleteFile(iNeverLoginFile);
        } else {
            FileSystem.FileExists(iNeverLoginFile, true);
        }
    }

    public boolean isLogining() {
        return iLogining;
    }

    public boolean isLogon() {
        if (iNetAPI != null) {
            return iNetAPI.isRemoteReady();
        }

        return false;
    }

    public boolean isUserRecord() {
        if (iNetAPI != null) {
            return iNetAPI.isUserRecord();
        }

        return false;
    }

    public long getLogonUser() {
        if (iNetAPI != null) {
            return iNetAPI.getLogonUser();
        }

        return 0;
    }

    public String getLogonUserName() {
        if (iNetAPI != null) {
            return iNetAPI.getLogonUserName();
        }

        return null;
    }

    public boolean changePassword(String aOldPwd, String aNewPwd) {
        if (iNetAPI != null) {
            String tUserName = getLogonUserName();

            if (iNetAPI.changePasswordByOld(aOldPwd, aNewPwd)) {
                logout();

                iLoginListener.onLogin(tUserName, aNewPwd);

                return true;
            }
        }

        return false;
    }

    private void loginOrCancel() {
        if (isUserRecord() == false && isNeedLogin()) {
            if (iHandler != null) {
                iHandler.sendEmptyMessage(KMESSAGE_SHOW_LOGIN_DIALOG);
            }
        } else {
            onLogon(isUserRecord() == false);
        }
    }

    private void onLoginFailed() {
        if (iLoginError == false) {
            iLoginError = true;
        }

        hideProgress(null);

        iLogining = false;
    }

    private void onLogon(boolean aCancel) {
        if (aCancel == false) {
            hideProgress(null);
            // hideProgress(R.string.LoginSuccess);
        }

        if (iLoginDialog != null && iLoginDialog.isShowing()) {
            iLoginDialog.dismiss();
        }

        iLogining = false;

        if (iExLoginListener != null) {
            final boolean tCancel = aCancel;

            new Thread(new Runnable() {
                @Override
                public void run() {
                    iExLoginListener.call(KEVENT_LOGIN, tCancel);
                }
            }).start();
        }
    }

    public void login(boolean aForce) {
        synchronized (iSyncLock) {
            if (isLogon() == false) {
                if (iLogining == false) {
                    iLogining = true;

                    iLoginError = false;

                    if (iNetAPI != null) {
                        if (aForce || iLoginCanceled == false) {
                            if (aForce || isUserRecord() == false) {
                                if (iHandler != null) {
                                    iHandler.sendMessage(Message.obtain(iHandler, KMESSAGE_SHOW_LOGIN_DIALOG, aForce));
                                }
                            } else {
                                if (isUserRecord()) {
                                    onLogon(false);
                                } else {
                                    iLogining = false;
                                }
                            }
                        } else {
                            if (iNetAPI.isRemoteReady() == false) {
                                loginOrCancel();
                            }
                        }
                    }
                }
            }
        }
    }

    private ListenerHolder<UserEventListener, Boolean> iExLoginListener = new ListenerHolder<UserEventListener, Boolean>() {
        @Override
        protected void onCall(UserEventListener aListener, int aID, Boolean aObject) {
            if (aListener != null && aObject != null) {
                switch (aID) {
                    case KEVENT_LOGIN: {
                        aListener.onLoginEvent(aObject);
                        break;
                    }
                    case KEVENT_PREPARE_LOGOUT: {
                        aListener.onPrepareLogout();
                        break;
                    }
                    case KEVENT_LOGOUT: {
                        aListener.onLogout(aObject);
                        break;
                    }
                }
            }
        }
    };

    public boolean addUserEventListener(UserEventListener aListener) {
        return iExLoginListener.addListener(aListener);
    }

    public boolean removeUserEventListener(UserEventListener aListener) {
        return iExLoginListener.removeListener(aListener);
    }

    private LoginDialog.LoginListener iLoginListener = new LoginDialog.LoginListener() {
        @Override
        public void onLogin(String aUserName, String aPassword) {
            iLoginError = false;

            showProgress(R.string.Logining);
            if (iNetAPI.login(aUserName, aPassword)) {

                onLogon(false);
            } else {
                onLoginFailed();
            }
        }

        @Override
        public void onRegister(String aUserName, String aPassword, String aMobile, String aEMail, String aFPQuestion, String aFPAnswer) {
            if (iNetAPI.getSecurityCode((short) 2052, ESECURITY_INFO_TYPE.ESECURITY_INFO_TYPE_EMAIL, aEMail)) {
                final String tUserName = aUserName;
                final String tPassword = aPassword;
                final String tFPQuestion = aFPQuestion;
                final String tFPAnswer = aFPAnswer;

                SecurityCodeDialog.SecurityCodeListener tListener = new SecurityCodeDialog.SecurityCodeListener() {
                    @Override
                    public void onShow(ActivityDialog aDialog) {
                    }

                    @Override
                    public void onDismiss(ActivityDialog aDialog) {
                    }

                    @Override
                    public void onCancel(ActivityDialog aDialog) {
                    }

                    @Override
                    public void onRegetSecurityCode(String aMobile, String aEMail) {
                        iNetAPI.getSecurityCode((short) 2052, ESECURITY_INFO_TYPE.ESECURITY_INFO_TYPE_EMAIL, aEMail);
                    }

                    @Override
                    public boolean onConfirmSecurityCode(String aMobile, String aEMail, int aSecurityCode) {
                        showProgress(R.string.Registering);

                        if (iNetAPI.userRegister(tUserName, tPassword, aMobile, aEMail, tFPQuestion, tFPAnswer, aSecurityCode)) {
                            hideProgress(null);

                            if (iLoginDialog != null && iLoginDialog.getRegisterDialog() != null) {
                                iLoginDialog.getRegisterDialog().dismiss();
                            }

                            return true;
                        } else {
                            // TODO 注册窗口不消失 这里应该是返回false的,但是返回false的话进度条就不会消失了,log打印的也是错误(服务器配额已满),但是实际上是注册成功了的
                            hideProgress(null);

                            if (iLoginDialog != null && iLoginDialog.getRegisterDialog() != null) {
                                iLoginDialog.getRegisterDialog().dismiss();
                            }

                            return true;
                        }

                    }
                };

                SecurityCodeDialog.Show(App.GetInstance(), tListener, aMobile, aEMail);
            }
        }

        @Override
        public void onShow(ActivityDialog aDialog) {
            iLoginDialog = (LoginDialog) aDialog;
        }

        @Override
        public void onDismiss(ActivityDialog aDialog) {
            iLoginDialog = null;

            if (iNetAPI.isRemoteReady() == false) {
                onLogon(true);
            }
        }

        @Override
        public void onCancel(ActivityDialog aDialog) {
        }
    };

    private ActivityDialog.DialogInterface iProgressListener = new ActivityDialog.DialogInterface() {
        @Override
        public void onShow(ActivityDialog aDialog) {
            if (iNetAPI.isRemoteReady() == false) {
                iProgressDialog = (ActivityProgressDialog) aDialog;
            } else {
                aDialog.dismiss();
            }
        }

        @Override
        public void onDismiss(ActivityDialog aDialog) {
            iProgressDialog = null;
        }

        @Override
        public void onCancel(ActivityDialog aDialog) {

        }
    };

    private IOTCallback.LoginResultCallback iLoginResultListener = new IOTCallback.LoginResultCallback() {
        @Override
        public void onLoginResultCallback(int aResult) {
            loginOrCancel();
        }
    };

    public boolean logout() {
        synchronized (iSyncLock) {
            if (this.isUserRecord()) {
                iLogining = false;

                iExLoginListener.call(KEVENT_PREPARE_LOGOUT, true);
                if (iNetAPI.logout()) {

                    iExLoginListener.call(KEVENT_LOGOUT, true);

                    return true;
                } else {
                    iExLoginListener.call(KEVENT_LOGOUT, false);
                }
            }
        }

        return false;
    }

    public String getUserName(long aUser) {
        return iNetAPI.retriveUserName(aUser);
    }

}
